package my.music.controller;

import cn.dev33.satoken.annotation.SaCheckRole;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import my.music.common.result.Result;
import my.music.common.result.ResultEnum;
import my.music.common.result.ResultModel;
import my.music.common.enums.UploadFileTypeEnum;
import my.music.config.UploadFilePathConfig;
import my.music.dao.FileInfoMapper;
import my.music.exception.UploadFileException;
import my.music.exception.UploadFileSuffixException;
import my.music.pojo.FileInfo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Set;

/**
 * 文件
 */
@RestController
@RequestMapping("file")
public class FileController {
    @Resource
    private UploadFilePathConfig uploadFilePathConfig;

    @Resource
    private FileInfoMapper fileInfoMapper;

    /**
     * 上传文件
     * @param file
     * @param fileTypeEnum
     * @return
     */
    private FileInfo uploadFile(MultipartFile file, UploadFileTypeEnum fileTypeEnum) throws UploadFileException, UploadFileSuffixException {
        String fileMD5 = "";
        try {
            Digester md5 = new Digester(DigestAlgorithm.MD5);
            fileMD5 = md5.digestHex(file.getBytes());
//            System.err.println(fileMD5);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 通过md5查询文件
        QueryWrapper qw = new QueryWrapper<>()
                .eq("md5", fileMD5);
        FileInfo fileInfo = fileInfoMapper.selectOne(qw);
        if (null != fileInfo){
            // 查询到文件
            if (fileInfo.getDeleted()){
                // 恢复文件
                fileInfo.setDeleted(false);
                fileInfoMapper.updateById(fileInfo);
            }
            return fileInfo;
        }
        // 文件不存在，创建文件

        // 获取后缀
        String fileName = file.getOriginalFilename();
        String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
        // 验证后缀是否合法
        Set<String> allowSuffix = new HashSet<>(fileTypeEnum.getSuffix());
        if (!allowSuffix.contains(fileSuffix.toLowerCase())){
            // 文件不合法
            throw new UploadFileSuffixException("文件验证不通过");
        }

        // 生成新文件名，雪花算法
        Snowflake snowflake = IdUtil.getSnowflake();
        String newFileName = String.valueOf(snowflake.nextId()) + fileSuffix;

        // 文件保存路径
//        String filePath = request.getSession().getServletContext().getRealPath("/upload") + "/" + newFileName;

        String uploadFolder = uploadFilePathConfig.getUploadFolder() + fileTypeEnum.getPath();
//        System.err.println(uploadFolder);
        File dataDir = new File(uploadFolder);
        if (!dataDir.exists()){
            // 判断目录是否存在，不存在则直接创建
            dataDir.mkdirs();
        }

        try {
            // 保存文件
            file.transferTo(new File(uploadFolder, newFileName));
        } catch (Exception e) {
            e.printStackTrace();
            throw new UploadFileException("文件添加异常");
            // 保存失败
        }
        String fileUrl = "/upload" + fileTypeEnum.getPath() + "/" + newFileName;

        FileInfo insertFileInfo = new FileInfo();
        insertFileInfo.setMd5(fileMD5);
        insertFileInfo.setUrl(fileUrl);

//        fileInfoMapper.insert(insertFileInfo);
        insertFileInfo.insert();

        return insertFileInfo;
    }

    /**
     * 上传歌曲
     * @param file 歌曲文件
     * @return
     */
    @PostMapping("api/song")
    public Result<FileInfo> uploadSong(MultipartFile file) throws UploadFileException, UploadFileSuffixException {
        if(file.isEmpty()){
            return ResultModel.error(ResultEnum.PARAMETER_NULL);
        }

        FileInfo fileInfo = uploadFile(file, UploadFileTypeEnum.SONG);
        return ResultModel.success(fileInfo);
    }

    /**
     * 上传图片
     * @param file 图片文件
     * @return
     */
    @PostMapping("api/img")
    public Result<FileInfo> uploadImg(MultipartFile file) throws UploadFileException, UploadFileSuffixException {
        if(file.isEmpty()){
            return ResultModel.error(ResultEnum.PARAMETER_NULL);
        }

        FileInfo fileInfo = uploadFile(file, UploadFileTypeEnum.IMAGE);
        return ResultModel.success(fileInfo);
    }

    /**
     * 根据文件id获取
     * （只能获取标记未删除的文件）
     * @param id 文件id|1
     * @return
     */
    @GetMapping("get/{id}")
    public Result<FileInfo> getFileInfoById(@PathVariable("id") BigInteger id){
        QueryWrapper qw = new QueryWrapper<>()
                .eq("id", id)
                .eq("is_deleted", false);
        FileInfo fileInfo = fileInfoMapper.selectOne(qw);
        return ResultModel.success(fileInfo);
    }

    /**
     * 根据文件id获取
     * @param id 文件id|1
     * @return
     */
    @GetMapping("api/get/{id}")
    public Result<FileInfo> getFileInfo(@PathVariable("id") BigInteger id){
        FileInfo fileInfo = fileInfoMapper.selectById(id);
        return ResultModel.success(fileInfo);
    }

    /**
     * 标记删除文件
     * @param id 文件id
     * @return
     */
    @GetMapping("api/remove/{id}")
    public Result removeFileInfo(@PathVariable("id") BigInteger id){
        FileInfo fileInfo = new FileInfo();
        fileInfo.setId(id);
        fileInfo.setDeleted(true);
        int i = fileInfoMapper.updateById(fileInfo);
        if (i > 0){
            return ResultModel.success();
        }
        return ResultModel.error(ResultEnum.SYSTEM_RUN_ERROR);
    }
}
